/******************************************************************************* * Copyright (c) 2012, Project: FP7-ICT-257930 Aniketos * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * - Neither the name of institution nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ package eu.aniketos.mtm.srs2activiti.wizard.pages; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Widget; import eu.aniketos.mtm.Activator; import eu.aniketos.mtm.idm.client.IdMClient; import eu.aniketos.mtm.idm.client.implementation.IdMClientImplementation; import eu.aniketos.mtm.mapping.BPPType; import eu.aniketos.mtm.mapping.MappingType; import eu.aniketos.mtm.mapping.PlaysType; import eu.aniketos.mtm.mapping.SRRType; import eu.aniketos.mtm.mapping.TypeType; import eu.aniketos.mtm.srs.RoleType; import eu.aniketos.mtm.srs.SecReqSpeType; import eu.aniketos.mtm.srs2activiti.wizard.Srs2ActivitiWizard; import eu.aniketos.mtm.util.MappingManager; import eu.aniketos.mtm.util.SrsManager; /** * * Page used to establish the correspondences between SRS roles and BPMN participants (1:n relationship). * */ public class NewPerformersRolePage extends CustomPage { private static final String PREFIX = "role_"; public static final String PERFORMERTYPE_SERVICE = "Service Provider"; public static final String PERFORMERTYPE_HUMAN = "Human Performer"; // Input SRS roles private ArrayList<RoleType> roleList; // List of composites, every of which contain all the participants that match a role private ArrayList<Composite> activitiCompositeMainList; // List of types private ArrayList<ArrayList<Combo>> performerTypeList; // List of participant names private ArrayList<ArrayList<Combo>> performerValueList; // List of buttons for removing a participant private ArrayList<ArrayList<Button>> removeButtonList; // List of buttons for adding a new participant to a role private ArrayList<Button> addButtonList; // Main scrollable composite private ScrolledComposite scrollComposite; private IdMClient idMClient; private String[] humanRoles = {}; private String[] serviceRoles = {}; private String[] roleTypes = {PERFORMERTYPE_SERVICE, PERFORMERTYPE_HUMAN}; /** * Constructor. * @param srs The SecReqSpeType root SRS element to be transformed. */ public NewPerformersRolePage(SecReqSpeType srs) { super("NewPerformersRolePage"); setTitle("Performers mapping"); setDescription("Map SRS Roles to BPMN Performers"); roleList = SrsManager.getInstance().extractRoleList(srs); int sizeList = roleList.size(); activitiCompositeMainList = new ArrayList<Composite>(sizeList); performerTypeList = new ArrayList<ArrayList<Combo>>(sizeList); performerValueList = new ArrayList<ArrayList<Combo>>(sizeList); removeButtonList = new ArrayList<ArrayList<Button>>(sizeList); addButtonList = new ArrayList<Button>(sizeList); // Get MTM preference for IDM String pathIdM = Activator.getDefault().getPreferenceStore().getString("IdM_file_path"); idMClient = new IdMClientImplementation(pathIdM); } /** * */ @Override public void createControl(Composite parent) { scrollComposite = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL); Composite composite = new Composite(scrollComposite, SWT.FILL); GridLayout gl = new GridLayout(); gl.numColumns = 2; composite.setLayout(gl); // Main control skeleton for the role/participant correspondence createMainControls(composite); // Scrollable parent composite scrollComposite.setContent(composite); scrollComposite.setExpandVertical(true); scrollComposite.setExpandHorizontal(true); scrollComposite.addControlListener(new ControlAdapter() { public void controlResized(ControlEvent e) { updateScroll(); } }); addListeners(); setControl(scrollComposite); setPageComplete(isReady()); } /** * Creates the main control skeleton for the role/participant correspondence. * @param composite The parent composite */ private void createMainControls(Composite composite) { if(roleList.size() == 0) { // No roles found Label emptyLabel = new Label(composite, SWT.NULL); emptyLabel.setText("No SRS Roles found"); return; } GridData gd; // Column titles Label rolesLabel = new Label(composite, SWT.NULL); rolesLabel.setText("SRS Roles"); gd = new GridData(); gd.horizontalAlignment = SWT.FILL; Label activitiLabel = new Label(composite, SWT.NULL); activitiLabel.setText("ACTIVITI Performers"); activitiLabel.setLayoutData(gd); performerValueList.clear(); performerTypeList.clear(); // For every role... for (int i = 0; i < roleList.size(); i++) { // Fill role description labels RoleType role = roleList.get(i); String roleValue = role.getValue().trim(); String roleString = roleValue; Label roleIdLabel = new Label(composite, SWT.NULL); roleIdLabel.setText(roleString); Composite compositeActiviti = new Composite(composite, SWT.BORDER); compositeActiviti.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); compositeActiviti.setLayout(new GridLayout(1, false)); Composite compositeMainActiviti = new Composite(compositeActiviti,SWT.NULL); compositeMainActiviti.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); compositeMainActiviti.setLayout(new GridLayout(1, false)); activitiCompositeMainList.add(compositeMainActiviti); // Add the first participant controls for this role addPerformerRecord(i); // Button for adding a new participant Button addButton = new Button(compositeActiviti, SWT.NONE); addButton.setText("Add new"); addButtonList.add(addButton); } } /** * Adds the controls needed for one new participant. * @param performerValue The suggested name of the participant. * @param index The index of the corresponding role. */ private void addPerformerRecord(int index) { if (index >= roleList.size()) { return; } // Get a reference to the composite that contain all the participants that match a role Composite composite = activitiCompositeMainList.get(index); Composite compositeSingleActiviti = new Composite(composite, SWT.NULL); compositeSingleActiviti.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); compositeSingleActiviti.setLayout( new GridLayout(3, false)); Composite typeComboComposite = new Composite(compositeSingleActiviti, SWT.NULL); typeComboComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); typeComboComposite.setLayout(new GridLayout(2, false)); // Performer type Label typeLabel = new Label(typeComboComposite, SWT.NULL); typeLabel.setText("Performer type"); Combo typeCombo = new Combo(typeComboComposite, SWT.BORDER | SWT.READ_ONLY); typeCombo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); typeCombo.setItems(this.roleTypes); typeCombo.setData(index+""); typeCombo.select(0); typeCombo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { updateRoleCombo (e.widget); } }); Composite roleComboComposite = new Composite(compositeSingleActiviti, SWT.NULL); roleComboComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); roleComboComposite.setLayout(new GridLayout(2, false)); // Performer role Label performerValueLabel = new Label(roleComboComposite, SWT.NULL); performerValueLabel.setText("Role name"); Combo combo = new Combo(roleComboComposite, SWT.BORDER | SWT.READ_ONLY); combo.setLayoutData(new GridData(SWT.FILL, SWT.LEFT, true, false)); combo.setItems(serviceRoles); combo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { setPageComplete(isReady()); } }); // Add the participant value text control to performerValueList ArrayList<Combo> performerValueSubList = null; ArrayList<Combo> performerTypeSubList = null; if (index >= performerValueList.size()) { // First participant for a role performerValueSubList = new ArrayList<Combo>(1); performerTypeSubList = new ArrayList<Combo>(1); performerValueList.add(performerValueSubList); performerTypeList.add(performerTypeSubList); } else { performerValueSubList = performerValueList.get(index); performerTypeSubList = performerTypeList.get(index); } performerValueSubList.add(combo); performerTypeSubList.add(typeCombo); // Create a button to remove this participant row Button removeButton = new Button(compositeSingleActiviti, SWT.NONE); removeButton.setText("Remove"); removeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { int index = -1; int subIndex = -1; for(int i = 0; i < removeButtonList.size(); i++) { ArrayList<Button> buttonList = removeButtonList.get(i); subIndex = buttonList.indexOf(e.widget); if(subIndex >= 0) { index = i; break; } } if(index >= 0) { removePerformerRecord(index, subIndex); } } }); // Add the remove button to removeButtonList ArrayList<Button> removeSubList = null; if (index >= removeButtonList.size()) { // First participant for a role removeSubList = new ArrayList<Button>(1); removeButtonList.add(removeSubList); } else { removeSubList = removeButtonList.get(index); } removeSubList.add(removeButton); // Enable the remove buttons only where there is more than one participant for a role updateRemoveButtons(index); // Refresh the screen refresh(); // Declare the page as complete when the form is full-filled setPageComplete(isReady()); } private void updateRoleCombo(Widget widget) { if(widget instanceof Combo){ Combo typeCombo = (Combo) widget; String index = (String) typeCombo.getData(); int i = new Integer(index).intValue(); ArrayList<Combo> performerTypeSubList = performerTypeList.get(i); int subindex = performerTypeSubList.indexOf(typeCombo); if(subindex >= 0) { Combo performerRoleCombo = performerValueList.get(i).get(subindex); performerRoleCombo.clearSelection(); String selectedRole = typeCombo.getText(); if(selectedRole.equals(PERFORMERTYPE_SERVICE)){ performerRoleCombo.setItems(serviceRoles); } else if (selectedRole.equals(PERFORMERTYPE_HUMAN)){ performerRoleCombo.setItems(humanRoles); } } } } /** * Removes one participant's controls. * @param index The index of the roles it belongs to. * @param subIndex The index of the participant for this role. */ private void removePerformerRecord(int index, int subIndex) { if (index >= roleList.size()) { return; } // Remove the references to the controls from the member lists performerValueList.get(index).remove(subIndex); removeButtonList.get(index).remove(subIndex); performerTypeList.get(index).remove(subIndex); // Remove the parent composite from the page Composite mainComposite = activitiCompositeMainList.get(index); Composite composite = (Composite)mainComposite.getChildren()[subIndex]; composite.dispose(); // Enable the remove buttons only where there is more than one participant for a role updateRemoveButtons(index); // Refresh the screen refresh(); // Declare the page as complete when the form is full-filled setPageComplete(isReady()); } @Override public void onAppear() { super.onAppear(); refreshList(); updateControls(); setPageComplete(isReady()); } public void refreshList (){ String humanList = idMClient.getGroupsListOfHuman(); humanRoles = splitSringToList(humanList); String serviceList = idMClient.getGroupsListOfService(); serviceRoles = splitSringToList(serviceList); } private String[] splitSringToList(String s){ String[] array = s.split(","); return array; } private void updateControls(){ for (ArrayList<Combo> comboList : performerValueList) { int index = performerValueList.indexOf(comboList); for (Combo combo : comboList) { int subindex = comboList.indexOf(combo); int selectionIndex = combo.getSelectionIndex(); String selectedType = null; if(selectionIndex != -1){ Combo typeCombo = this.performerTypeList.get(index).get(subindex); selectedType = typeCombo.getText(); String selectedRole = combo.getItem(selectionIndex); selectionIndex = findRoleIndex(selectedRole, selectedType); if(selectedType.equals(PERFORMERTYPE_SERVICE)){ combo.setItems(serviceRoles); } else if(selectedType.equals(PERFORMERTYPE_HUMAN)){ combo.setItems(humanRoles); } } else{ combo.setItems(serviceRoles); } combo.select(selectionIndex); } } } private int findRoleIndex(String role, String type){ if(type.equals(PERFORMERTYPE_SERVICE)){ for (int i = 0; i < serviceRoles.length; i++) { String serviceRole = serviceRoles[i]; if(serviceRole.equals(role)){ return i; } } } else if (type.equals(PERFORMERTYPE_HUMAN)){ for (int i = 0; i < humanRoles.length; i++) { String humanRole = humanRoles[i]; if(humanRole.equals(role)){ return i; } } } return 0; } /** * Refresh the page to show the last changes. */ private void refresh() { Shell shell = getShell(); shell.layout(true, true); updateScroll(); } /** * Adds listeners to controls. */ private void addListeners() { addRoleListeners(); } /** * Adds the suitable listener to every Add button. */ private void addRoleListeners() { for (int i = 0; i < addButtonList.size(); i++) { Button addButton = addButtonList.get(i); addButton.addSelectionListener(new AddSelectionAdapter(i)); } } /** * */ @Override public boolean isEmpty() { return roleList.size() == 0; } /** * Updates the mapping model. */ @Override protected void pageComplete() { updateModel(); } /** * */ @Override public boolean canFlipToNextPage() { return isPageComplete(); } /** * Finish button disabled. */ @Override public boolean canFinish() { return false; } /** * Checks whether the form is full-filled. * @return True when full-filled, false when a Text control is empty. */ private boolean isReady() { for (ArrayList<Combo> array : performerValueList) { for (Combo combo : array) { if (!isComboNonEmpty(combo)) { setErrorMessage("There are empty fields."); return false; } else{ setErrorMessage(null); } } } return true; } /** * Updates the enabled/disabled state of all Remove buttons. */ private void updateAllRemoveButtons() { for(int i = 0; i < removeButtonList.size(); i++) { updateRemoveButtons(i); } } /** * Sets Remove buttons enabled only when there is more than one participant for one role. * @param index The index of the role. */ private void updateRemoveButtons(int index) { ArrayList<Button> buttonList = removeButtonList.get(index); boolean enabled = false; if(buttonList.size() > 1) { enabled = true; } for(Button button : buttonList) { button.setEnabled(enabled); } } /** * Updates the main scrollbar. */ private void updateScroll() { Rectangle r = scrollComposite.getClientArea(); scrollComposite.setMinSize(scrollComposite.getChildren()[0].computeSize(r.width, SWT.DEFAULT)); } /** * Updates the mapping model based on the page form. */ private void updateModel() { int size = roleList.size(); if(size > 0) { MappingType mapping = ((Srs2ActivitiWizard)getWizard()).getMapping(); MappingManager manager = MappingManager.getInstance(); // Clear the existing plays relationships manager.resetPlaysList(mapping); List<BPPType> bppList = new ArrayList<BPPType>(); // For every role... for (int i = 0; i < size; i++) { RoleType role = roleList.get(i); // Create the role mapping element SRRType srr = manager.createSRRole(role.getId().toString(), role.getValue().trim()); ArrayList<Combo> performerValueSublist = performerValueList.get(i); int subSize = performerValueSublist.size(); // For every participant binded to this role... for (int j = 0; j < subSize; j++) { Combo valueCombo = performerValueSublist.get(j); // Get role type Combo typeCombo = performerTypeList.get(i).get(j); // Create the participant mapping element String performerId = PREFIX + role.getId() + "_" + j; TypeType roleType = null; if(typeCombo.getText().equals(PERFORMERTYPE_SERVICE)){ roleType = TypeType.SERVICE; } else if (typeCombo.getText().equals(PERFORMERTYPE_HUMAN)){ roleType = TypeType.HUMAN; } BPPType bpp = null; for (BPPType bppType : bppList) { if(bppType.getType().equals(roleType) && bppType.getValue().equals(valueCombo.getText().trim())){ // Clone Bpp bpp = manager.createBPPart(bppType.getId(),valueCombo.getText().trim(), roleType); } } if(bpp == null){ bpp = manager.createBPPart(performerId,valueCombo.getText().trim(), roleType); bppList.add(bpp); } // Create and add the plays relationship PlaysType plays = manager.createPlays(srr, bpp); manager.addPlays(mapping, plays); } } } } /** * * Adapter for Add button. * */ class AddSelectionAdapter extends SelectionAdapter { int index; /** * Constructor. * @param index The index of the role. */ public AddSelectionAdapter(int index) { this.index = index; } /** * Adds the controls necessary for the new participant. * Controls are empty by default. */ @Override public void widgetSelected(final SelectionEvent e) { addPerformerRecord(index); } } }